博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python操作三大主流数据库(14)python操作redis之新闻项目实战②新闻数据的展示及修改、删除操作...
阅读量:7023 次
发布时间:2019-06-28

本文共 17260 字,大约阅读时间需要 57 分钟。

python操作三大主流数据库(14)python操作redis之新闻项目实战②新闻数据的展示及修改、删除操作

项目目录:

├── flask_redis_news.py├── forms.py├── init_news.py├── redis_news.py├── static│   ├── bootstrap-3.3.7-dist│   │   ├── css│   │   ├── fonts│   │   └── js│   ├── bootstrap-3.3.7-dist.zip│   ├── datatables.min.css│   ├── datatables.min.js│   ├── img│   │   └── news│   ├── index.css│   ├── jquery-3.3.1.min.js│   └── main.css├── templates│   ├── admin│   │   ├── add.html│   │   ├── admin_base.html│   │   ├── index.html│   │   └── update.html│   ├── cat.html│   ├── detail.html│   ├── home_base.html│   └── index.html

 1.服务端代码flask_redis_news.py

#coding:utf-8import sysdefaultencoding = 'utf-8'if sys.getdefaultencoding() != defaultencoding:    reload(sys)    sys.setdefaultencoding(defaultencoding)import osfrom datetime import datetimefrom werkzeug import secure_filenamefrom flask import Flask, request, render_template, redirect, flash, url_for, abortfrom flask_uploads import UploadSet, configure_uploads, IMAGES, patch_request_classfrom forms import NewsFormfrom redis_news import RedisNewsapp = Flask(__name__)app.config['SECRET_KEY'] = 'adfa@4314#31AD23#2'app.config['UPLOADED_PHOTOS_DEST'] = "/data/three_db_python/redis_version01/static/img/news"query = RedisNews()photos = UploadSet('photos', IMAGES)configure_uploads(app, photos)patch_request_class(app)  # set maximum file size, default is 16MB@app.route("/", methods = ['GET'])def index():    ''' 获取新闻列表 '''    news_list = query.get_all_news()    return render_template("index.html", news_list = news_list)@app.route("/cat/
/", methods = ['GET'])def cat(name): ''' 获取新闻列表 ''' news_list = query.get_news_from_cat(name) return render_template("cat.html", news_list = news_list)@app.route("/detail/
/", methods = ['GET'])def detail(pk): ''' 获取新闻列表 ''' news_obj = query.get_news_from_id(pk) return render_template("detail.html", obj = news_obj)@app.route("/admin/", methods = ['GET'])@app.route("/admin/
/", methods = ['GET'])def admin(page = None): ''' 获取后台新闻列表 ''' if page is None: page = 1 page_data = query.paginate(page, 5) return render_template("admin/index.html", page_data = page_data)@app.route("/admin/add/", methods = ['GET','POST'])def admin_add(): ''' 从后台页面添加新闻 ''' form = NewsForm() news_obj = {} # 提交增加 if form.validate_on_submit(): # 图片文件名 filename = photos.save(form.photo.data) news_obj['title'] = form.title.data news_obj['news_type'] = form.news_type.data news_obj['img_url'] = form.img_url.data news_obj['content'] = form.content.data news_obj['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') news_obj['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') query.add_new_from_page(news_obj) flash('添加成功') return redirect(url_for('admin')) return render_template("admin/add.html", form = form)@app.route("/admin/update/
/", methods = ['GET','POST'])def admin_update(pk): ''' 获取后台新闻列表 ''' # 获取新闻 news_obj = query.get_news_from_id(pk) if news_obj is None: abort('no this news') form = NewsForm(data = news_obj) # 提交修改 if form.validate_on_submit(): news_obj['title'] = form.title.data news_obj['news_type'] = form.news_type.data news_obj['img_url'] = form.img_url.data news_obj['content'] = form.content.data news_obj['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') query.update_news(pk, news_obj) flash('新闻修改成功') return redirect(url_for('admin')) return render_template("admin/update.html", form = form)@app.route("/admin/delete/
/", methods = ['GET','POST'])def admin_delete(pk): ''' 删除新闻 ''' news_obj = query.get_news_from_id(pk) if news_obj: query.delete_news(pk, news_obj) return 'yes' return 'no'if __name__ == "__main__": app.run(debug = True,host="0.0.0.0")

 

 

2.辅助类新闻的具体操作redis_news.py

#coding:utf-8import mathimport redisNEWS_FIELDS = (    "title",    "img_url",    "content",    "is_valid",    "news_type",    "created_at",    "updated_at")class RedisNews(object):    def __init__(self):        # 如果返回是二进制类似 b'3\xe6\x9c\x885\xe6\x97\xa5\xe...'需要加decode_responses=True        try:            self.r = redis.StrictRedis(host = 'localhost',             port=6379,encoding='utf-8',              decode_responses=True,               db=1)        except Exception as e:            print('redis connect faild')            def _news_id(self, int_id):        ''' 新闻id '''        return 'news:%d' % int(int_id)    def _news_type(self, news_type):        ''' 新闻类型 '''        return 'news_type:%s' % news_type    def _news_list_name(self):        ''' 新闻列表名称 '''        return 'news'    def add_new_from_page(self, news_obj):        ''' 从页面新增新闻数据 '''        # 记录news_id的数字自增1        int_id = self.r.incr('news_id', amount=1)        # 获取新闻id        news_id = self._news_id(int_id)        # 新闻列表中添加        self.r.lpush(self._news_list_name(), int_id)        # 新闻类型中添加信息        news_type = news_obj['news_type']        self.r.sadd(news_type, int_id)        # 新闻内容中添加信息        self.r.hmset(news_id, news_obj)    def add_news(self, news_obj):        ''' 新增新闻数据 '''        # 获取到新闻的id        int_id = int(self.r.incr('news_id'))        # 拼接新闻数据Hash key(news:2)        news_id = self._news_id(int_id)        # 存储新闻数据(hash)        rest = self.r.hmset(news_id, news_obj)        # 存储新闻的id list        self.r.lpush(self._news_list_name(), int(int_id))        # 存储新闻的类别-新闻id(set)        news_type = _news_type(news_obj['news_type'])        self.r.sadd(news_type, int_id)        return rest    def add_news_with_transaction(self, news_obj):        ''' 使用事务来新增新闻数据 '''        pipe = self.r.pipeline(transaction=True)        int_id = self.r.incr('news_id')        news_id = self._news_id(int_id)        # 使用列表list获取新闻的id        pipe.lpush(self._news_list_name(), int_id)        # 使用hash来保存新闻具体内容        pipe.hmset(news_id, news_obj)        # 使用hash来保存新闻分类信息        news_type = self._news_type(news_obj['news_type'])        pipe.sadd(news_type, int_id)        rest = pipe.execute()        return rest    def get_all_news(self):        ''' 获取所有新闻信息 '''        # 获取id列表        id_list = self.r.lrange(self._news_list_name(), 0, -1)        data_list = []        for int_id in id_list:            # 获取具体新闻内容            news_id = self._news_id(int_id)            data = self.r.hgetall(news_id)            data['id'] = int_id            # print(data)            data_list.append(data)        return data_list    def get_news_from_id(self, news_id):        ''' 根据新闻id获取新闻内容 '''        news_id = self._news_id(news_id)        # 根据新闻id获取新闻内容        news_obj = self.r.hgetall(news_id)        return news_obj    def get_news_from_cat(self, cat_name):        ''' 根据新闻类型获取新闻内容 '''        news_list = []        # 获取新闻类型        news_type = self._news_type(cat_name)        # print(news_type)        # 获取新闻类型集合中新闻id的列表        id_list = self.r.smembers(news_type)        print(id_list)        for int_id in id_list:            # 获取新闻id            news_id = self._news_id(int_id)            # 根据新闻id获取新闻内容            data = self.r.hgetall(news_id)            data['id'] = int_id            news_list.append(data)        return news_list    def update_news(self, pk, news_obj):        ''' 新闻的修改 '''        news_id = self._news_id(pk)        # 修改新闻        rest = self.r.hmset(news_id, news_obj)        return rest    def delete_news(self, pk, news_obj):        '''             新闻的删除,物理删除            关于常用的方法可以通过查询redis的命令类型判断是list,string还是hash或者set            1.命令列表定位到具体命令:http://www.redis.cn/commands.html#hash            2.找到命令后,查询api的用法http://redis-py.readthedocs.io/en/latest/        '''        # 获取新闻id        news_id = self._news_id(pk)        # 从新闻列表中删除新闻id        self.r.lrem(self._news_list_name(), 0, pk)        # 从新闻的类型set集合中清理新闻id        news_type = self._news_type(news_obj['news_type'])        self.r.srem(news_type, pk)        # 从新闻的内容hash列表中清理具体的新闻内容NEWS_FIELDS(具体的列信息)        self.r.hdel(news_id, *NEWS_FIELDS)    def paginate(self, page=1, per_page=5):        ''' 新闻后台分页 '''        if page is None:            page = 1        data_list = []        # 开始页,结束页面        start = (page - 1)*per_page        end = page*per_page - 1        # 获取所有新闻列表(计算页码使用)        list_ids = self.r.lrange(self._news_list_name(), 0, -1)        # 获取新闻列表        id_list = self.r.lrange(self._news_list_name(), start, end)        # print('id_list%s' % id_list)        for int_id in id_list:            news_id = self._news_id(int_id)            # 根据新闻id获取新闻内容            data = self.r.hgetall(news_id)            data['id'] = int_id            data_list.append(data)        # print('data_list%s' % data_list)        return Pagenation(data_list, page, per_page, list_ids)    def init_news(self, data_list):        ''' 批量导入新闻数据 '''        for news_obj in data_list:            rest = self.add_news_with_transaction(news_obj)            print(rest)class Pagenation(object):    ''' 分页类 '''    def __init__(self, data_list, now_page, per_page, list_ids):        self.now_page = now_page        self.data_list = data_list        self.per_page = per_page        self.list_ids = list_ids    @property    def page(self):        ''' 当前页 '''        return self.now_page    @property    def items(self):        ''' 返回页面数据 '''        return self.data_list    @property    def prev_num(self):        ''' 上一页 '''        return self.now_page - 1    @property    def next_num(self):        ''' 下一页页码 '''        return self.now_page + 1    @property    def has_prev(self):        ''' 是否有上一页 '''        return self.now_page > 1    @property    def has_next(self):        ''' 是否有下一页 '''        return self.per_page == len(self.data_list)    def iter_pages(self):        ''' 页码 '''        # 获取所有的id长度(即新闻条数)除以每页显示的页面,得到取进一位的整数        total_page = math.ceil(len(self.list_ids)/self.per_page)        # print('total_page=%d' % total_page)        return range(1, total_page)

3.表单类forms.py

from flask_wtf import FlaskFormfrom wtforms import StringField, TextAreaField, SubmitField, SelectFieldfrom flask_wtf.file import FileField, FileRequired, FileAllowedfrom wtforms.validators import DataRequiredclass NewsForm(FlaskForm):    """新闻表单数据验证"""    title = StringField(label = '新闻标题', validators = [DataRequired('请输入标题')],        description = '请输入标题',        render_kw={
'required':'required', 'class':'form-control'}) content = TextAreaField(label = '新闻内容', validators = [DataRequired('请输入新闻内容')], description = '请输入新闻内容', render_kw={
'required':'required', 'class':'form-control'}) news_type = SelectField('新闻类型', choices = [('推荐','推荐'), ('百家', '百家'),('本地','本地'), ('图片','图片')]) img_url = StringField(label='新闻图片', description='请输入图片地址', render_kw={
'required':'required', 'class':'form-control'}) photo = FileField('图片上传', validators=[FileAllowed(['png', 'JPEG', 'jpg'], '只能上传图片!'), FileRequired('文件未选择!')]) submit = SubmitField('提交')

4.前台展示页面

①模板home_base.html

  
{% block head %} 首页 {% endblock %}

新闻列表

{% block content %}
{% endblock %}
{% block extrajs %}
{% endblock %}

②首页index.html

{% extends 'home_base.html' %}{% block content%}
{% for obj in news_list %}
{% endfor %}
图片 简介
图片

{ { obj.title }} { { obj.created_at }}

{% endblock %}{% block extrajs %}{% endblock %}

③详情页detail.html

{% extends 'home_base.html' %}  {% block head %}  新闻详情  {% endblock %}{% block content%}

新闻详情,来自新闻id> {
{obj.id}}

{ { obj.content }}
图片

{ { obj.title }} { { obj.created_at }}

{% endblock %}

④分类页面cat.html

{% extends 'home_base.html' %}{% block head%}{<div></div>   { name }}{% endblock %}{% block content%}
{% for obj in news_list %}
{% endfor %}
图片 简介
图片

{ { obj.title }} { { obj.created_at }}

{% endblock %}{% block extrajs %}{% endblock %}

5.后台管理页面

①后台模板页面admin/admin_base.html

    
{% block head %} 首页 {% endblock %}

②后台首页admin/index.html

{% extends 'admin/admin_base.html' %}{% block head %}新闻后台首页{% endblock %}{% block content %}        
{% for msg in get_flashed_messages() %}

{

{msg}}

{% endfor %}
{% for new_obj in page_data.items %}
{% endfor %}
编号 新闻标题 类别 添加时间 操作
{
{ new_obj.id }}
{
{ new_obj.title }}
{
{new_obj.types }}
{
{new_obj.created_at }}
修改删除
{% endblock %}{% block extrajs %}{% endblock %}

③后台添加页面admin/add.html

{% extends 'admin/admin_base.html' %}{% block head %}新闻添加页面{% endblock %}{% block content %}        
{
{ form.news_type }}
{
{ form.photo }} {% for error in form.photo.errors %}
{
{ error }}
{% endfor %}

新闻图片上传

新闻图片的路径

{
{ form.img_url }}
{
{ form.content }}
{
{ form.csrf_token }} {
{ form.submit }}
{% endblock %}

 

 

④后台新闻更新页面admin/update.html

{% extends 'admin/admin_base.html' %}{% block head %}修改新闻{% endblock %}{% block content %}    
{
{form.title}}
{
{ form.news_type }}
{
{ form.img_url }}
{
{ form.content }}
{
{ form.csrf_token }} {
{ form.submit }}
{% endblock %}

 

转载于:https://www.cnblogs.com/reblue520/p/8549389.html

你可能感兴趣的文章
hidesBottomBarWhenPushed 设置为NO的问题
查看>>
cisco常用命令详解
查看>>
谁在追踪谁?
查看>>
HTTP请求返回状态码详解
查看>>
句柄类
查看>>
GitLab
查看>>
【常用配置】Spring框架web.xml通用配置
查看>>
[leetcode 240]Search a 2D Matrix II
查看>>
域名指的是这一级目录
查看>>
[Angular] Creating an Observable Store with Rx
查看>>
[转]Porting to Oracle with Entity Framework NLog
查看>>
chmod更改文件的权限
查看>>
oracle 10g/11g RAC 启停归档模式
查看>>
poj3461 Oulipo
查看>>
OAuth2.0学习(1-12)开源的OAuth2.0项目和比较
查看>>
Gitlab,这也就O了???
查看>>
2014 百度之星 1003 题解 Xor Sum
查看>>
Linux中在主机上实现对备机上文件夹及文件的操作的C代码实现
查看>>
iOS 块的简单理解
查看>>
idea中如何配置git以及在idea中初始化git
查看>>